3.0. Packaging
Why package the agent before adding features?
An importable package gives the ADK CLI, tests, MCP server, A2A server, and container one implementation to execute. Without that boundary, examples drift into scripts with different paths, dependencies, and startup behavior.
How is the project organized?
agents/python/
pyproject.toml Runtime/dev dependencies and tool configuration
uv.lock Exact dependency resolution
mise.toml Stable development commands
Dockerfile Non-root A2A runtime image
src/agent/
__init__.py ADK root_agent discovery
agent.py Composition root
budget.py Token accounting and per-session budget
config.py Typed environment boundary
config_check.py Masked effective-configuration diagnostic
model.py OpenAI-compatible or optional Gemini selection
models.py Trusted domain types
data.py Seed-to-runtime data access
tools.py Read-only incident/log tools
skills.py Least-privilege Agent Skills
mcp_server.py stdio/HTTP MCP server
mcp_client.py ADK MCP client adapter
longterm.py Explicit cross-session incident notes
memory.py Runbook retrieval
retrieval.py Optional local semantic retrieval
report.py Schema-validated triage report
resilience.py Read/model deadlines and retry policy
structured_report/ Dedicated structured-output sub-agent package
workflow.py Explicit workflow graph
delegation.py In-process specialist delegation
guardrails.py Tool/model policy and safe errors
actions.py Approved writes and audit
pii.py Boundary redaction callbacks
telemetry.py OpenTelemetry setup
server.py Persistent A2A application
tests/ Offline tests
evals/ Model-backed ADK/MLflow evaluation
The sibling agents/data/ directory is immutable seed input. .state/ is generated writable state and is ignored by Git.
Why use a src layout?
With module-root = "src", imports resolve to the installed package rather than accidentally resolving a same-named directory from the working tree:
That catches missing packaging metadata early and makes the container use the same import contract as tests.
Which entrypoints are stable?
adk run src/agent Interactive terminal agent
adk web src ADK developer UI
python -m agent.mcp_server MCP over configured transport
python -m agent.server Persistent A2A ASGI server
mise.toml wraps each command so learners and CI do not have to remember implementation details.
Why separate runtime and development dependencies?
The final image needs ADK, MCP, state, security, and telemetry libraries. Ruff, ty, pytest, pip-audit, MLflow evaluation, and ADK eval extras are development gates and should not expand the runtime attack surface. uv sync --locked --no-dev in the container enforces that separation.
How do data paths stay portable?
config.py derives repository defaults relative to the installed source and lets deployments override them:
The image bundles /app/data read-only. A writable volume owns /app/state. No machine-specific absolute path is committed.
What is the packaging checkpoint?
Expected name: agentops_agent. Then run the same import from a directory outside src/ to prove the installed package, rather than the current working directory, supplies it.